package com.xzr.yespaper.controller;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

import com.xzr.yespaper.bean.Paper;
import com.xzr.yespaper.bean.User;
import com.xzr.yespaper.service.PaperService;
import com.xzr.yespaper.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.configurationprocessor.json.JSONArray;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.*;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Controller
public class PaperMainController {

    @Autowired
    PaperService paperService;

    @Autowired
    UserService userService;

    /**
     * 得到所有论文 Get all papers (all information)
     * @return JSON形式论文列表 {code: false}/ {code: true, papers: []}
     * @throws JSONException（没用这玩意）
     */
    @PostMapping("/getall")
    @ResponseBody
    public String get() throws JSONException {
        try{
            List<Paper> papers = paperService.getAll();
            String list = JSON.toJSONString(papers);
            JSONObject ret = new JSONObject();
            ret.put("code",true);
            ret.put("papers", list);
            return ret.toString();
        } catch (JSONException e) {
            JSONObject ret = new JSONObject();
            ret.put("code",false);
            return ret.toString();
        }
    }

    /**
     * 得到所有已发表论文 Get all published papers
     * @return JSON形式论文列表 {code: false}/ {code: true, papers: []}
     * @throws JSONException（没用这玩意）
     */
    @PostMapping("/getallpub")
    @ResponseBody
    public String getpub() throws JSONException {
        try{
            List<Paper> papers = paperService.getAllPub();
            String list = JSON.toJSONString(papers);
            JSONObject ret = new JSONObject();
            ret.put("code",true);
            ret.put("papers", list);
            return ret.toString();
        } catch (JSONException e) {
            JSONObject ret = new JSONObject();
            ret.put("code",false);
            return ret.toString();
        }
    }

    /**
     * 上传论文 Upload papers
     * @param file pdf文件 pdf files
     * @param paper 对象映射 paper object (lombok.Data) automatically get info from front end
     * @return JSON {code:true/false} return state: successful or not
     * @throws IOException（没用这玩意）
     * @throws JSONException（没用这玩意）
     */
    @PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("pdf") MultipartFile file, Paper paper) throws IOException, JSONException, DocumentException {
        if(!file.isEmpty()){
            // file.getOriginalFilename()
            // 设置文件名 Set file name (use uuid not original file name to keep information safe)
            String uuid = UUID.randomUUID().toString();
            // 设置路径 Save file in static folder
            String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            file.transferTo(new File(path + "static/pdfs/"+uuid+".pdf"));
            paper.setAddress(uuid);
            //System.out.println(path + "static/pdfs/"+uuid+".pdf");
            //BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(path + "static/pdfs/"+uuid+".pdf")));
//            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("D:/YesPaper/yespaper-web/target/classes/static/pdfs/0a3ef364-9536-4254-a265-3f2b745329b9.pdf")));
//            setWatermark(bos, path + "static/pdfs/"+uuid+".pdf");
            // 设置提交时间 Update edit time
            String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            paper.setDate(time);
            // 设置审稿人 Automatically assign reviewers (By their field)
            String[] fieldArray = {"Artificial intelligence","Big data","Computer security",
                    "Cloud computing","Database","Programing language","Internet of things"};
            List<User> teachers = userService.getTeachers();
            ArrayList fitTeachers = new ArrayList();
            for(int i=0;i<fieldArray.length;i++){
                if(
                    paper.getKeyword().indexOf(fieldArray[i])>=0
                    ||paper.getAbstracts().indexOf(fieldArray[i])>=0
                    ||paper.getTitle().indexOf(fieldArray[i])>=0
                ){
                    for(int j=0;j<teachers.size();j++){
                        if(teachers.get(j).getField().indexOf(fieldArray[i])>=0){
                            fitTeachers.add(teachers.get(j).getUsername());
                        }
                    }
                }
            }
            // 没有匹配则添加所有 If not match field, randomly choose 3 of all as reviewers
            if(fitTeachers.isEmpty()){
                for(int j=0;j<teachers.size();j++){
                   fitTeachers.add(teachers.get(j).getUsername());
                }
            }
            String choosen = "";
            for(int k=0;k<3;k++){
                int num = (int)(Math.random()*fitTeachers.size());
                choosen += fitTeachers.get(num) + ";";
                fitTeachers.remove(num);
            }
            // test
            System.out.print(fitTeachers);
            paper.setReviewer(choosen);
            // 设置状态 Set paper state as "awaiting approval"
            paper.setState("awaiting approval");
//            System.out.println(paper);
            // 如果成功 success，返回 code:true
            if(paperService.createPaper(paper)){
                JSONObject ret = new JSONObject();
                ret.put("code",true);
                //System.out.println(ret);
                return ret.toString();
            }
        }
        JSONObject ret = new JSONObject();
        ret.put("code",false);
        //System.out.println(ret);
        return ret.toString();
    }

    /**
     * 更改论文 Edit paper file
     * @param file pdf文件 pdf file
     * @param paper 对象映射 paper object (lombok.Data) automatically get info from front end
     * @return JSON {code:true/false}
     * @throws IOException（没用这玩意）
     * @throws JSONException（没用这玩意）
     */
    @PostMapping("/updatepaper")
    @ResponseBody
    public String update(@RequestParam("pdf") MultipartFile file, Paper paper) throws IOException, JSONException {
        if(!file.isEmpty()) {
            // file.getOriginalFilename()
            // 设置文件名 Set file name (use uuid not original file name to keep information safe)
            String uuid = UUID.randomUUID().toString();
            // 设置路径 Save file in static folder
            String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            file.transferTo(new File(path + "static/pdfs/" + uuid + ".pdf"));
            paper.setAddress(uuid);
            if(!paperService.updatePaperAddress(paper)){
                JSONObject ret = new JSONObject();
                ret.put("code",false);
                return ret.toString();
            }
        }
        // 设置提交时间 Update edit time
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        paper.setDate(time);
        // 如果成功success，返回code:true
        if(!paperService.updatePaperInfo(paper)){
            JSONObject ret = new JSONObject();
            ret.put("code",false);
            return ret.toString();
        }
        JSONObject ret = new JSONObject();
        ret.put("code",true);
        return ret.toString();
    }

    /**
     * 删除论文 Delete paper
     * @param paper 对象映射 paper object (lombok.Data) automatically get info from front end
     * @return JSON {code:true/false}
     * @throws JSONException（没用这玩意）
     */
    @PostMapping("/deletepaper")
    @ResponseBody
    public String delete(Paper paper) throws JSONException {
        if(paperService.deletePaper(paper)){
            JSONObject ret = new JSONObject();
            ret.put("code",true);
            return ret.toString();
        }
        JSONObject ret = new JSONObject();
        ret.put("code",false);
        return ret.toString();
    }

    /**
     * 发表论文 Publish paper
     * @param paper 对象映射 paper object (lombok.Data) automatically get info from front end
     * @return JSON {code:true/false}
     * @throws JSONException（没用这玩意）
     */
    @PostMapping("/publishpaper")
    @ResponseBody
    public String publish(Paper paper) throws JSONException, IOException, DocumentException {
        Paper thisPaper = paperService.getPaperByID(paper);
        if(thisPaper.getState().equals("publishable")){
            paper.setState("published");
            // 加水印更新地址存储 Add watermark and update address storage
            String uuid = UUID.randomUUID().toString();
            String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(path + "static/pdfs/"+uuid+".pdf")));
            setWatermark(bos, path + "static/pdfs/"+thisPaper.getAddress()+".pdf");
            paper.setAddress(uuid);
            if(!paperService.updatePaperAddress(paper)){
                JSONObject ret = new JSONObject();
                ret.put("code",false);
                return ret.toString();
            }
            // 保存状态 Update paper state
            if(paperService.updatePaperState(paper)){
                JSONObject ret = new JSONObject();
                ret.put("code",true);
                return ret.toString();
            }
        }
        JSONObject ret = new JSONObject();
        ret.put("code",false);
        return ret.toString();
    }

    /**
     * set digital signature
     * @param bos The output pdf
     * @param input The original position of pdf
     * @throws DocumentException
     * @throws IOException
     */
    public static void setWatermark(BufferedOutputStream bos, String input)
            throws DocumentException, IOException {
        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = new PdfStamper(reader, bos);
        int total = reader.getNumberOfPages() + 1;
        // get the number of pages of the paper
        PdfContentByte digitalSignature;
        PdfGState gs = new PdfGState();
        // set the transparency of digital signature
        gs.setStrokeOpacity(0.4f);
        try {
            for (int i = 1; i < total; i++) {
                digitalSignature = stamper.getUnderContent(i);
                // add the digital signature under the pdf
                gs.setFillOpacity(0.7f);
                digitalSignature.beginText();
                // start to set the digital signature
                String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
                Image image = Image.getInstance(path + "static/utils/img/" + "logo1.png");
                // Image image = Image.getInstance("D:/YesPaper/yespaper-web/target/classes/static/utils/img/logo1.png");
                image.setAlignment(Image.LEFT | Image.TEXTWRAP);

                image.setAbsolutePosition(230, 60);
//                image.setRotation(30);
//                image.setRotationDegrees(-30);
                //rotate
                image.scaleAbsolute(326, 295);
                // set the size
                digitalSignature.setGState(gs);
                digitalSignature.addImage(image);

                digitalSignature.endText();
                digitalSignature.stroke();
                // end the set
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            digitalSignature = null;
            gs = null;
        }
        stamper.close();
    }

}
